﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Linq;
using Dimebrain.TweetSharp;
using Dimebrain.TweetSharp.Extensions;
using Dimebrain.TweetSharp.Fluent;
using Dimebrain.TweetSharp.Model;
using System.Windows.Threading;

namespace TwitualStudio
{
    /// <summary>
    /// Interaction logic for TwitualStudioUserControl.xaml
    /// </summary>
    public partial class TwitualStudioUserControl : UserControl
    {
        private TwitterClientInfo clientInfo;
        private OAuthToken requestToken;
        private TwitterUser user;
        protected long? lastId;

        public TwitualStudioUserControl()
        {
            InitializeComponent();

            txtOAuthPIN.Text = Properties.Settings.Default.OAuthPin;
            clientInfo = new TwitterClientInfo
            {
                ClientName = "Twitual Studio",
                ClientUrl = "http://twitualstudio.codeplex.com",
                ClientVersion = "0.0.0.1Alpha",
                ConsumerKey = Properties.Settings.Default.ConsumerKey,
                ConsumerSecret = Properties.Settings.Default.ConsumerSecret
            };

            FluentTwitter.SetClientInfo(clientInfo);
        }

        private void btnRefresh_Click(object sender, RoutedEventArgs e)
        {
            var request = CreateRequest().Statuses().OnHomeTimeline();
            if (lastId.HasValue)
            {
                request = request.Since(lastId.Value);
            }
            else
            {
                request = request.Take(50);
            }
            RequestAsyncSafe(request, RequestComplete);

            return;
        }

        public static void RequestAsyncSafe(ITwitterLeafNode request, TwitterWebCallback callback)
        {
            System.Threading.ThreadPool.QueueUserWorkItem(o =>
            {
                try
                {
                    var req = (ITwitterLeafNode)o;
                    var result = req.Request();
                    if (callback != null)
                    {
                        callback(req, result);
                    }
                }
                catch
                {
                    //Deliberately empty catch
                }
            }, request);
        }

        void RequestComplete(object sender, TwitterResult result)
        {
            if (Application.Current.Dispatcher != Dispatcher.CurrentDispatcher)
            {
                Application.Current.Dispatcher.Invoke(new Action<object, TwitterResult>(RequestComplete), sender, result);
                return;
            }

            if (!(result.IsFailWhale || result.IsNetworkError || result.IsTwitterError))
            {
                OnSuccessfulRequest(result);
            }
        }

        protected void OnSuccessfulRequest(TwitterResult result)
        {
            var tweets = result.AsStatuses();
            if (tweets == null || tweets.Count() == 0) return;
            lstTimeline.SelectedIndex = -1;
            lstTimeline.ItemsSource = tweets;

            lastId = tweets.Max(t => t.Id);
        }

        private void btnClear_Click(object sender, RoutedEventArgs e)
        {
            lstTimeline.ItemsSource = null;
        }

        private void btnSettingsSave_Click(object sender, RoutedEventArgs e)
        {
            toggleSettings.IsChecked = false;

            //Authenticate
            if (requestToken == null) return;

            // exchange the unauthenticated request token with an authenticated access token,
            // and remember to persist this authentication pair for future use

            var accessToken = FluentTwitter.CreateRequest()
                .Authentication
                .GetAccessToken(Properties.Settings.Default.ConsumerKey, Properties.Settings.Default.ConsumerSecret, requestToken.Token, txtOAuthPIN.Text.Trim());

            var response = accessToken.Request();
            var result = response.AsToken();
            if (result == null || String.IsNullOrEmpty(result.Token))
            {
                var error = response.AsError();
                MessageBox.Show(error.ErrorMessage);
                return;
            }

            // make an authenticated call to Twitter with the token and secret
            Properties.Settings.Default.AccessToken = result.Token;
            Properties.Settings.Default.AccessTokenSecret = result.TokenSecret;
            Properties.Settings.Default.Save();

            if (!Authenticate())
            {
                MessageBox.Show("There was a problem authenticating. Please try again.");
                return;
            }

            Properties.Settings.Default.OAuthPin = txtOAuthPIN.Text;
            Properties.Settings.Default.Save();
            btnRefresh_Click(null, null);
        }

        private void toggleSettings_Checked(object sender, RoutedEventArgs e)
        {
            txtOAuthPIN.Focus();
        }

        private void txtOAuthPIN_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter || e.Key == Key.Return)
                btnSettingsSave_Click(null, null);
        }

        private void btnGetOAuthPin_Click(object sender, RoutedEventArgs e)
        {
            requestToken = GetRequestToken(Properties.Settings.Default.ConsumerKey, Properties.Settings.Default.ConsumerSecret);
            if (requestToken == null) return;

            // automatically starts the default web browser, sending the 
            // user to the authorization URL.
            FluentTwitter.CreateRequest()
                .Authentication
                .AuthorizeDesktop(Properties.Settings.Default.ConsumerKey, Properties.Settings.Default.ConsumerSecret, requestToken.Token);
        }

        private static OAuthToken GetRequestToken(string consumerKey, string consumerSecret)
        {
            var requestToken = FluentTwitter.CreateRequest()
                .Authentication
                .GetRequestToken(consumerKey, consumerSecret);

            var response = requestToken.Request();

            var result = response.AsToken();
            if (result != null) return result;

            var error = response.AsError();

            var mesg = error != null ? error.ErrorMessage
                : !String.IsNullOrEmpty(response.ResponseHttpStatusDescription) ? response.ResponseHttpStatusDescription
                : response.ResponseHttpStatusCode.ToString();

            MessageBox.Show(mesg);
            return null;
        }

        public bool Authenticate()
        {
            if (String.IsNullOrEmpty(Properties.Settings.Default.AccessToken) ||
                String.IsNullOrEmpty(Properties.Settings.Default.AccessTokenSecret))
            {
                return false;
            }

            // check that the stored authentication is valid
            var twitter = CreateRequest().Account().VerifyCredentials();
            try
            {
                var response = twitter.Request();
                if (response.IsTwitterError || response.IsNetworkError || response.IsFailWhale)
                {
                    return false;
                }

                user = response.AsUser();

                return true;
            }
            catch
            {
                return false;
            }
        }

        public IFluentTwitter CreateRequest()
        {
            return FluentTwitter
                .CreateRequest()
                .AuthenticateWith(
                    Properties.Settings.Default.AccessToken,
                    Properties.Settings.Default.AccessTokenSecret);
        }

    }
}